package com.smart.community.user.service.impl;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.smart.community.commons.dto.property.PropertyCompanyDTO;
import com.smart.community.commons.exception.BusinessException;
import com.smart.community.commons.result.PageResult;
import com.smart.community.feign.property.service.IUserPropertyCompanyAuthFeign;
import com.smart.community.user.dto.UserPropertyCompanyDTO;
import com.smart.community.user.dto.UserPropertyCompanyQueryDTO;
import com.smart.community.user.entity.UserPropertyCompany;
import com.smart.community.user.mapper.UserPropertyCompanyMapper;
import com.smart.community.user.service.UserPropertyCompanyService;
import com.smart.community.user.vo.UserPropertyCompanyVO;

import io.seata.spring.annotation.GlobalTransactional;
import lombok.extern.slf4j.Slf4j;

/**
 * 用户物业公司关联服务实现类
 * 
 * @author Wu.Liang
 */
@Slf4j
@Service
public class UserPropertyCompanyServiceImpl extends ServiceImpl<UserPropertyCompanyMapper, UserPropertyCompany>
        implements UserPropertyCompanyService {

    @Autowired
    private IUserPropertyCompanyAuthFeign propertyCompanyAuthFeign;

    // ==================== 缓存常量定义 ====================
    private static final String USER_PROPERTY_COMPANIES_CACHE_PREFIX = "user:property:companies:";
    private static final String USER_COMPANY_IDS_CACHE_PREFIX = "user:company:ids:";
    private static final String PROPERTY_COMPANY_USERS_CACHE_PREFIX = "property:company:users:";
    
    // 缓存过期时间（秒）
    private static final long USER_PROPERTY_COMPANIES_CACHE_EXPIRE = 1800; // 30分钟
    private static final long USER_COMPANY_IDS_CACHE_EXPIRE = 1800; // 30分钟
    private static final long PROPERTY_COMPANY_USERS_CACHE_EXPIRE = 1800; // 30分钟

    // ==================== 缓存工具方法 ====================
    
    /**
     * 清除用户物业公司关联缓存
     */
    private void clearUserPropertyCompanyCache(Long userId) {
        try {
            String[] cacheKeys = {
                USER_PROPERTY_COMPANIES_CACHE_PREFIX + userId,
                USER_COMPANY_IDS_CACHE_PREFIX + userId
            };
            
            for (String cacheKey : cacheKeys) {
                // 这里需要注入CacheService，暂时注释掉
                // cacheService.delete(cacheKey);
            }
            
            log.debug("清除用户物业公司关联缓存成功，用户ID：{}", userId);
        } catch (Exception e) {
            log.warn("清除用户物业公司关联缓存失败，用户ID：{}", userId, e);
        }
    }
    
    /**
     * 清除物业公司用户列表缓存
     */
    private void clearPropertyCompanyUsersCache(Long propertyCompanyId) {
        try {
            String cacheKey = PROPERTY_COMPANY_USERS_CACHE_PREFIX + propertyCompanyId;
            // 这里需要注入CacheService，暂时注释掉
            // cacheService.delete(cacheKey);
            log.debug("清除物业公司用户列表缓存成功，物业公司ID：{}", propertyCompanyId);
        } catch (Exception e) {
            log.warn("清除物业公司用户列表缓存失败，物业公司ID：{}", propertyCompanyId, e);
        }
    }

    @GlobalTransactional
    public void associateUserWithCompany(Long userId, Long companyId) throws Exception {
        if (userId == null || companyId == null) {
            throw new IllegalArgumentException("用户ID和物业公司ID不能为空");
        }
        
        // 检查是否已存在关联
        LambdaQueryWrapper<UserPropertyCompany> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserPropertyCompany::getUserId, userId)
               .eq(UserPropertyCompany::getPropertyCompanyId, companyId);
        
        if (this.count(wrapper) > 0) {
            throw new BusinessException("用户已关联该物业公司");
        }
        
        UserPropertyCompany userPropertyCompany = new UserPropertyCompany();
        userPropertyCompany.setUserId(userId);
        userPropertyCompany.setPropertyCompanyId(companyId);
        userPropertyCompany.setStatus(1);
        userPropertyCompany.setCreateTime(LocalDateTime.now());
        userPropertyCompany.setUpdateTime(LocalDateTime.now());
        userPropertyCompany.setVersion(1);
        
        this.save(userPropertyCompany);
    }

    @GlobalTransactional
    public void disassociateUserFromCompany(Long userId, Long companyId) throws Exception {
        if (userId == null || companyId == null) {
            throw new IllegalArgumentException("用户ID和物业公司ID不能为空");
        }
        
        LambdaQueryWrapper<UserPropertyCompany> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserPropertyCompany::getUserId, userId)
               .eq(UserPropertyCompany::getPropertyCompanyId, companyId);
        
        UserPropertyCompany userPropertyCompany = this.getOne(wrapper);
        if (userPropertyCompany == null) {
            throw new BusinessException("用户物业公司关联不存在");
        }
        
        userPropertyCompany.setStatus(0);
        userPropertyCompany.setUpdateTime(LocalDateTime.now());
        
        this.updateById(userPropertyCompany);
    }

    public List<UserPropertyCompanyVO> getUserPropertyCompanies(Long userId) throws Exception {
        LambdaQueryWrapper<UserPropertyCompany> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserPropertyCompany::getUserId, userId)
               .eq(UserPropertyCompany::getStatus, 1)
               .orderByDesc(UserPropertyCompany::getCreateTime);
        
        List<UserPropertyCompany> userPropertyCompanies = this.list(wrapper);
        
        return userPropertyCompanies.stream()
                .map(this::convertToVO)
                .collect(Collectors.toList());
    }

    public List<Long> getUserCompanyIds(Long userId) throws Exception {
        LambdaQueryWrapper<UserPropertyCompany> wrapper = new LambdaQueryWrapper<>();
        wrapper.select(UserPropertyCompany::getPropertyCompanyId)
               .eq(UserPropertyCompany::getUserId, userId)
               .eq(UserPropertyCompany::getStatus, 1);
        
        List<UserPropertyCompany> userPropertyCompanies = this.list(wrapper);
        
        return userPropertyCompanies.stream()
                .map(UserPropertyCompany::getPropertyCompanyId)
                .collect(Collectors.toList());
    }

    @GlobalTransactional
    public void batchAssociateUsersWithCompany(List<Long> userIds, Long companyId) throws Exception {
        if (userIds == null || userIds.isEmpty()) {
            throw new IllegalArgumentException("用户ID列表不能为空");
        }
        
        List<UserPropertyCompany> userPropertyCompanies = new ArrayList<>();
        for (Long userId : userIds) {
            // 检查是否已存在关联
            LambdaQueryWrapper<UserPropertyCompany> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(UserPropertyCompany::getUserId, userId)
                   .eq(UserPropertyCompany::getPropertyCompanyId, companyId);
            
            if (this.count(wrapper) == 0) {
                UserPropertyCompany userPropertyCompany = new UserPropertyCompany();
                userPropertyCompany.setUserId(userId);
                userPropertyCompany.setPropertyCompanyId(companyId);
                userPropertyCompany.setStatus(1);
                userPropertyCompany.setCreateTime(LocalDateTime.now());
                userPropertyCompany.setUpdateTime(LocalDateTime.now());
                userPropertyCompany.setVersion(1);
                userPropertyCompanies.add(userPropertyCompany);
            }
        }
        
        this.saveBatch(userPropertyCompanies);
    }

    @GlobalTransactional
    public void batchDisassociateUsersFromCompany(List<Long> userIds, Long companyId) throws Exception {
        if (userIds == null || userIds.isEmpty()) {
            throw new IllegalArgumentException("用户ID列表不能为空");
        }
        
        LambdaQueryWrapper<UserPropertyCompany> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserPropertyCompany::getPropertyCompanyId, companyId)
               .in(UserPropertyCompany::getUserId, userIds);
        
        List<UserPropertyCompany> userPropertyCompanies = this.list(wrapper);
        
        for (UserPropertyCompany userPropertyCompany : userPropertyCompanies) {
            userPropertyCompany.setStatus(0);
            userPropertyCompany.setUpdateTime(LocalDateTime.now());
        }
        
        this.updateBatchById(userPropertyCompanies);
    }

    // UserPropertyCompanyService 接口方法实现

    public PageResult<UserPropertyCompanyVO> getUserPropertyCompanyList(UserPropertyCompanyQueryDTO queryDTO) throws Exception {
        // 构建查询条件
        QueryWrapper<UserPropertyCompany> queryWrapper = new QueryWrapper<>();
        
        if (queryDTO.getUserId() != null) {
            queryWrapper.eq("user_id", queryDTO.getUserId());
        }
        
        if (queryDTO.getPropertyCompanyId() != null) {
            queryWrapper.eq("property_company_id", queryDTO.getPropertyCompanyId());
        }
        
        if (queryDTO.getStatus() != null) {
            queryWrapper.eq("status", queryDTO.getStatus());
        }
        
        queryWrapper.orderByDesc("create_time");
        
        // 分页查询
        Page<UserPropertyCompany> page = new Page<>(queryDTO.getCurrent(), queryDTO.getSize());
        IPage<UserPropertyCompany> userPropertyCompanyPage = this.page(page, queryWrapper);
        
        // 转换为VO
        List<UserPropertyCompanyVO> userPropertyCompanyVOList = userPropertyCompanyPage.getRecords().stream()
                .map(this::convertToVO)
                .collect(Collectors.toList());
        
        // 构建分页结果
        PageResult<UserPropertyCompanyVO> pageResult = new PageResult<>();
        pageResult.setRecords(userPropertyCompanyVOList);
        pageResult.setTotal(userPropertyCompanyPage.getTotal());
        pageResult.setSize((int) userPropertyCompanyPage.getSize());
        pageResult.setCurrent((int) userPropertyCompanyPage.getCurrent());
        pageResult.setPages((int) userPropertyCompanyPage.getPages());
        
        return pageResult;
    }

    public UserPropertyCompanyVO getUserPropertyCompany(Long id) throws Exception {
        UserPropertyCompany userPropertyCompany = this.getById(id);
        return userPropertyCompany != null ? convertToVO(userPropertyCompany) : null;
    }

    @GlobalTransactional
    public void createUserPropertyCompany(UserPropertyCompanyDTO userPropertyCompanyDTO) throws Exception {
        UserPropertyCompany userPropertyCompany = new UserPropertyCompany();
        BeanUtils.copyProperties(userPropertyCompanyDTO, userPropertyCompany);
        userPropertyCompany.setCreateTime(LocalDateTime.now());
        userPropertyCompany.setUpdateTime(LocalDateTime.now());
        userPropertyCompany.setVersion(1);
        
        this.save(userPropertyCompany);
    }

    @GlobalTransactional
    public void updateUserPropertyCompany(Long id, UserPropertyCompanyDTO userPropertyCompanyDTO) throws Exception {
        UserPropertyCompany userPropertyCompany = this.getById(id);
        if (userPropertyCompany == null) {
            throw new BusinessException("用户物业公司关联不存在");
        }
        
        BeanUtils.copyProperties(userPropertyCompanyDTO, userPropertyCompany);
        userPropertyCompany.setUpdateTime(LocalDateTime.now());
        
        this.updateById(userPropertyCompany);
    }

    @GlobalTransactional
    public void deleteUserPropertyCompany(Long id) throws Exception {
        UserPropertyCompany userPropertyCompany = this.getById(id);
        if (userPropertyCompany == null) {
            throw new BusinessException("用户物业公司关联不存在");
        }
        
        userPropertyCompany.setStatus(0);
        userPropertyCompany.setUpdateTime(LocalDateTime.now());
        
        this.updateById(userPropertyCompany);
    }

    @GlobalTransactional
    public void updateUserPropertyCompanyStatus(Long id, Integer status) throws Exception {
        UserPropertyCompany userPropertyCompany = this.getById(id);
        if (userPropertyCompany == null) {
            throw new BusinessException("用户物业公司关联不存在");
        }
        
        userPropertyCompany.setStatus(status);
        userPropertyCompany.setUpdateTime(LocalDateTime.now());
        
        this.updateById(userPropertyCompany);
    }

    @GlobalTransactional
    public void assignUserPropertyCompanies(Long userId, List<Long> propertyCompanyIds) throws Exception {
        // 删除原有关联
        LambdaQueryWrapper<UserPropertyCompany> deleteWrapper = new LambdaQueryWrapper<>();
        deleteWrapper.eq(UserPropertyCompany::getUserId, userId);
        this.remove(deleteWrapper);
        
        // 新增关联
        if (propertyCompanyIds != null && !propertyCompanyIds.isEmpty()) {
            List<UserPropertyCompany> userPropertyCompanies = propertyCompanyIds.stream()
                    .map(propertyCompanyId -> {
                        UserPropertyCompany userPropertyCompany = new UserPropertyCompany();
                        userPropertyCompany.setUserId(userId);
                        userPropertyCompany.setPropertyCompanyId(propertyCompanyId);
                        userPropertyCompany.setStatus(1);
                        userPropertyCompany.setCreateTime(LocalDateTime.now());
                        userPropertyCompany.setUpdateTime(LocalDateTime.now());
                        userPropertyCompany.setVersion(1);
                        return userPropertyCompany;
                    })
                    .collect(Collectors.toList());
            
            this.saveBatch(userPropertyCompanies);
        }
    }

    public List<UserPropertyCompanyVO> getPropertyCompanyUsers(Long propertyCompanyId) throws Exception {
        LambdaQueryWrapper<UserPropertyCompany> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserPropertyCompany::getPropertyCompanyId, propertyCompanyId)
               .eq(UserPropertyCompany::getStatus, 1)
               .orderByDesc(UserPropertyCompany::getCreateTime);
        
        List<UserPropertyCompany> userPropertyCompanies = this.list(wrapper);
        
        return userPropertyCompanies.stream()
                .map(this::convertToVO)
                .collect(Collectors.toList());
    }

    /**
     * 转换为VO对象
     * 
     * @param userPropertyCompany 用户物业公司关联实体
     * @return 用户物业公司关联VO
     */
    private UserPropertyCompanyVO convertToVO(UserPropertyCompany userPropertyCompany) {
        if (userPropertyCompany == null) {
            return null;
        }
        
        UserPropertyCompanyVO vo = new UserPropertyCompanyVO();
        BeanUtils.copyProperties(userPropertyCompany, vo);
        
        // 获取物业公司详细信息
        try {
            PropertyCompanyDTO propertyCompany = propertyCompanyAuthFeign.getPropertyCompanyById(userPropertyCompany.getPropertyCompanyId());
            if (propertyCompany != null) {
                vo.setPropertyCompanyName(propertyCompany.getCompanyName());
                vo.setPropertyCompanyCode(propertyCompany.getCompanyCode());
            }
        } catch (Exception e) {
            // 如果获取物业公司信息失败，不影响主流程，只记录日志
            log.warn("获取物业公司信息失败，物业公司ID：{}，错误：{}", userPropertyCompany.getPropertyCompanyId(), e.getMessage());
        }
        
        return vo;
    }
} 